package api

import (
	"context"
	"errors"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/go-redis/redis/v8"
	"go-chain-api/global"
	models "go-chain-api/internal/model"
	"go-chain-api/utils"
	"go-chain-api/utils/mail"
	"go.mongodb.org/mongo-driver/bson"
	"log"
	"math/rand"
	"net/http"
	"time"
)

type UserAPI struct {
}

type ResetPassword struct {
	Code     string `bson:"code" json:"code"`
	Password string `bson:"password" json:"password"`
	Email    string `bson:"email" json:"email"`
}

// 监听用户到期时间
func UserExpireTask() {

	ticker := time.NewTicker(5 * time.Second)
	defer ticker.Stop()
	for {
		select {
		case <-ticker.C: // 等待定时器触发
			changeUserStatus()
		}
	}

}

func changeUserStatus() {
	//查询maturityTime大于0并且小于当前时间戳--会员过期了
	userClient := global.DBEngine.Database(global.DbConfig.DbName).Collection("user")
	filter := bson.D{{"maturityTime", bson.D{{"$gt", 0}, {"$lt", time.Now().Unix()}}}}
	update := bson.D{
		{"$set", bson.D{
			{"maturityTime", 0},
		}},
	}
	_, err := userClient.UpdateMany(context.TODO(), filter, update)
	if err != nil {
		log.Fatal(err)
	}

	//这里我觉得可以在在watch_address_config和generate_address_config表里加一个字段
	//默认是开启的  在这里关闭 主要用于扫块判断这个这个字段是不是开启的 这样就能避免他过期了 还在监听
}

func (u UserAPI) ResetPassword(c *gin.Context) {
	var resetPassword ResetPassword
	err := c.ShouldBindJSON(&resetPassword)
	if err != nil {
		response := utils.GetResponse(err, utils.ParseDataError, nil, "zh-tw")
		c.JSON(http.StatusOK, response)
		return
	}
	var userInfo models.User
	userClient := global.DBEngine.Database(global.DbConfig.DbName).Collection("user")
	err = userClient.FindOne(context.TODO(), bson.M{"email": resetPassword.Email}).Decode(&userInfo)
	if err != nil {
		response := utils.GetResponse(errors.New(""), utils.UserNotExist, nil, "zh-tw")
		c.JSON(http.StatusOK, response)
		return
	}

	var emailCode models.EmailCode
	code, err := emailCode.GetLatest(resetPassword.Email)
	if err != nil {
		response := utils.GetResponse(errors.New(""), utils.EmailCodeError, nil, "zh-tw")
		c.JSON(http.StatusOK, response)
		return
	}
	if resetPassword.Code != code.Code {
		response := utils.GetResponse(errors.New(""), utils.CodeError, nil, "zh-tw")
		c.JSON(http.StatusOK, response)
		return
	}
	timestamp := time.Unix(int64(code.Timestamp), 0)
	// 加上 60 秒
	newTimestamp := timestamp.Add(60 * time.Second)
	if newTimestamp.Before(time.Now()) {
		response := utils.GetResponse(errors.New(""), utils.CodeExpired, nil, "zh-tw")
		c.JSON(http.StatusOK, response)
		return
	}

	userInfo.Password = utils.MD5(resetPassword.Password)
	err = userInfo.EditPassword()
	if err != nil {
		response := utils.GetResponse(err, utils.UpdateError, nil, "zh-tw")
		c.JSON(http.StatusOK, response)
		return
	}
	response := utils.GetResponse(nil, utils.Success, nil, "zh-tw")
	c.JSON(http.StatusOK, response)

}

// 获取邮箱验证码
func (u UserAPI) GetEmailCode(c *gin.Context) {
	code := generateNumericCode(6)
	//
	////userInfo := c.MustGet("userInfo").(models.User)
	var emailCode models.EmailCode
	email := c.Query("email")

	emailCode.Code = code
	emailCode.Email = email
	emailCode.Timestamp = uint64(time.Now().Unix())
	err := emailCode.Create(emailCode)
	if err != nil {
		response := utils.GetResponse(err, utils.InsertError, nil, "zh-tw")
		c.JSON(http.StatusOK, response)
		return
	}

	// 发送普通单发邮件
	emailParams := mail.Options{
		MailHost: global.EmailConfig.Host,
		MailPort: global.EmailConfig.Port,
		MailUser: global.EmailConfig.User,
		MailPass: global.EmailConfig.Password,
		MailTo:   email,
		Subject:  "验证码",
		Body:     fmt.Sprintf("您的验证码是:[%s] ", code),
	}
	mail.Send(&emailParams)
	//_, err = mail.SendSingleEmail(0, email, global.EmailConfig.FromEmail, true, global.EmailConfig.FromEmail, "天晟科技", fmt.Sprintf("您的验证码是:[%s] ", code), "验证码", "")
	if err != nil {
		response := utils.GetResponse(err, utils.EmailCodeError, nil, "zh-tw")
		c.JSON(http.StatusOK, response)
		return
	}

	response := utils.GetResponse(nil, utils.Success, nil, "zh-tw")
	c.JSON(http.StatusOK, response)
}

// 生成随机验证码
func generateNumericCode(length int) string {
	rand.Seed(time.Now().UnixNano()) // 使用当前时间作为随机数种子

	b := make([]byte, length)
	for i := range b {
		b[i] = byte('0' + rand.Intn(10)) // 生成 0 到 9 的随机数字
	}

	return string(b)
}

func (u UserAPI) CreatePayAddress(c *gin.Context) {
	userId := c.PostForm("userId")
	var response global.Response

	generateAddressClient := global.DBEngine.Database(global.DbConfig.DbName).Collection("generate_address_config")
	count, err := generateAddressClient.CountDocuments(context.TODO(), bson.D{{"userId", userId}})
	if err != nil {
		response = global.Response{
			Code: http.StatusInternalServerError,
			Data: nil,
			Msg:  err.Error(),
		}
		c.JSON(http.StatusOK, response)
		return
	}

	if count != 0 {
		response = global.Response{
			Code: http.StatusInternalServerError,
			Data: nil,
			Msg:  "user pay address is exist",
		}
		c.JSON(http.StatusOK, response)
		return
	}

	var registerConfig []models.RegisterConfig
	registerConfigClient := global.DBEngine.Database(global.DbConfig.DbName).Collection("register_config")
	find, _ := registerConfigClient.Find(context.TODO(), bson.D{})
	err = find.All(context.TODO(), &registerConfig)
	if err != nil {
		response = global.Response{
			Code: http.StatusInternalServerError,
			Data: nil,
			Msg:  err.Error(),
		}
		c.JSON(http.StatusOK, response)
		return
	}

	if len(registerConfig) == 0 {
		response = global.Response{
			Code: http.StatusInternalServerError,
			Data: nil,
			Msg:  "register config is not setting",
		}
		c.JSON(http.StatusOK, response)
		return
	}

	//for _, config := range registerConfig {
	//	err = models.GenerateAddress(userId, config.ChainId, config.ChainName)
	//	if err != nil {
	//		response = global.Response{
	//			Code: http.StatusInternalServerError,
	//			Data: nil,
	//			Msg:  err.Error(),
	//		}
	//		c.JSON(http.StatusOK, response)
	//		return
	//	}
	//}

	response = global.Response{
		Code: http.StatusOK,
		Data: nil,
		Msg:  "success",
	}

	c.JSON(http.StatusOK, response)
}

func (u UserAPI) GetEmail(c *gin.Context) {
	userInfo := c.MustGet("userInfo").(models.User)
	response := global.Response{
		Code: http.StatusOK,
		Data: userInfo.Email,
		Msg:  "success",
	}
	c.JSON(http.StatusOK, response)
}

func (u UserAPI) SetVerifyStatus(c *gin.Context) {
	var data models.WithdrawVerify
	err := c.ShouldBindJSON(&data)
	if err != nil {
		response := utils.GetResponse(err, utils.ParseDataError, nil, "zh-tw")
		c.JSON(http.StatusOK, response)
		return
	}
	userInfo := c.MustGet("userInfo").(models.User)

	err = models.SetStatus(userInfo.Id, data.Status)
	response := global.Response{
		Code: http.StatusOK,
		Data: err,
		Msg:  "success",
	}
	c.JSON(http.StatusOK, response)
}

func (u UserAPI) GetVerifyStatus(c *gin.Context) {
	userInfo := c.MustGet("userInfo").(models.User)
	err := models.GetStatus(userInfo.Id)
	response := global.Response{
		Code: http.StatusOK,
		Data: err,
		Msg:  "success",
	}
	c.JSON(http.StatusOK, response)
}

// 获取邮箱验证码
func (u UserAPI) GetRedisEmailCode(c *gin.Context) {

	userInfo := c.MustGet("userInfo").(models.User)
	language := c.MustGet("language").(string)
	code := generateNumericCode(6)
	//
	////userInfo := c.MustGet("userInfo").(models.User)
	var emailCode models.EmailCode
	email := c.Query("email")
	//userId := c.Query("userId")

	emailCode.Code = code
	emailCode.Email = email
	emailCode.UserId = userInfo.Id
	emailCode.Timestamp = uint64(time.Now().Unix())

	setUserInfo(global.RedisEngine, emailCode.UserId, "code", emailCode.Code)
	//setUserInfo(global.RedisEngine, emailCode.UserId, "email", emailCode.Email)

	// 发送普通单发邮件
	options := mail.Options{
		MailHost: global.EmailConfig.Host,
		MailPort: global.EmailConfig.Port,
		MailUser: global.EmailConfig.User,
		MailPass: global.EmailConfig.Password,
		MailTo:   email,
		Subject:  "验证码",
		Body:     fmt.Sprintf("您的验证码是:[%s] ", code),
	}
	err := mail.Send(&options)
	//_, err := mail.SendSingleEmail(0, email, global.EmailConfig.FromEmail, true, global.EmailConfig.FromEmail, "天晟科技", fmt.Sprintf("您的验证码是:[%s] ", code), "验证码", "")
	if err != nil {
		response := utils.GetResponse(err, utils.EmailCodeError, nil, language)
		c.JSON(http.StatusOK, response)
		return
	}

	response := utils.GetResponse(nil, utils.Success, nil, language)
	c.JSON(http.StatusOK, response)
}
func setUserInfo(rdb *redis.Client, userID, emailCode, value string) {
	key := fmt.Sprintf("userId:%s:%s", userID, emailCode)
	_, err := rdb.Set(context.Background(), key, value, 5*time.Minute).Result()
	if err != nil {
		log.Fatalf("Failed to set userId info: %v", err)
	}
}

func (u UserAPI) SetUserEmail(c *gin.Context) {
	var data models.User
	err := c.ShouldBindJSON(&data)
	userInfo := c.MustGet("userInfo").(models.User)
	language := c.MustGet("language").(string)
	if err != nil {
		response := utils.GetResponse(err, utils.ParseDataError, nil, language)
		c.JSON(http.StatusOK, response)
		return
	}
	id := userInfo.Id
	code, err := getUserInfo(global.RedisEngine, id, "code")
	if code != data.EmailCode {
		response := utils.GetResponse(nil, utils.EmailCodeError, nil, language)
		c.JSON(http.StatusOK, response)
		return
	}

	err = userInfo.UpdateEmail(data)
	response := global.Response{
		Code: http.StatusOK,
		Data: err.Error(),
		Msg:  "success",
	}
	c.JSON(http.StatusOK, response)
}

func getUserInfo(rdb *redis.Client, id, emailCode string) (string, error) {
	key := fmt.Sprintf("userId:%s:%s", id, emailCode)
	val, err := rdb.Get(context.Background(), key).Result()
	if err != nil {
		if err == redis.Nil {
			// Redis返回nil表示键不存在
			return "", fmt.Errorf("user info not found")
		}
		return "", err
	}
	return val, nil
}
